热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

笔者|放入_Redis基础认识内存式NoSQL数据库及简单使用Redis

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Redis基础认识内存式NoSQL数据库及简单使用Redis相关的知识,希望对你有一定的参考价值。Redis

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Redis基础认识内存式NoSQL数据库及简单使用Redis相关的知识,希望对你有一定的参考价值。



Redis基础(一)认识内存式NoSQL数据库及简单使用Redis


  • NoSQL与RDBMS
  • Redis简介
    • 数据结构
    • 数据类型
      • String类型
      • Hash类型
      • List类型
      • Set类型
      • Zset类型


  • 命令
    • 通用命令
    • String类型的常用命令
    • Hash类型的常用命令
    • List类型的常用命令
    • Set类型的常用命令
    • Zset类型的常用命令
    • BitMap类型的常用命令
    • HyperLogLog类型的常用命令

  • Windows版Redis
    • 部署
    • 测试
    • 桌面工具

  • Linux版Redis
    • 部署
    • 启动
      • 服务端
      • 客户端

    • 关闭
      • 客户端
      • 服务端




NoSQL与RDBMS

RDBMS就是关系型数据库管理系统,常见的mysql、SQL Server、Oracle就属于这种模型。∵可以体现数据之间的关系,支持事务,可以保证业务完整性和稳定性,小数据量时性能也较好,一般用作业务性数据存储系统。

但是!!!高并发时,分布式服务器的许多访问同时操作RDBMS,分分钟宕机。。。

此时就需要缓冲机制实现数据库的高并发。这些工具(Redis、HBase、MongoDB)就是NoSQL【不是字面的不是SQL,而是Not only SQL:非关系型数据库】,常用于高并发高性能场景下的数据缓存/数据库存储。

NoSQL读写速度非常快,并发量非常高,但是高并发是通过读写内存实现的,相对读写硬盘的RDBMS不稳定,对事务性的支持也不太友好。NoSQL的语法也不像SQL那么统一,每种SQL都有自己的语法和命令。

NoSQL可以实现读写分离,例如:
读请求:不读取MySQL,读取Redis;
写请求:直接写到MySQL。

由于正常情况大部分业务都是读多写少,读取不稳定但是写入稳定,总体来看稳定性影响不大,但是性能提升很大。当然必要时也可以使用另一个Redis缓冲,解决写入时的高并发。


Redis简介

Redis官网介绍Redis:
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker. Redis provides data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes, and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions, and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

看不懂的可以看中文的。Redis有中文文档,对新手很友好:
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

网站长的差不多,直接看中文的命令指导或者从中文网站下载,都没问题。

Redis是用地球最强的C语言写的,可以操作硬件,性能很好。且是基于内存实现数据的读写,读写很快。其是分布式的,拓展性稳定性很好。支持事务,拥有各种丰富的数据结构

数据库用于永久性存储,大数据领域可以将高性能读写结果存储/采集在HDFS中。
缓存是临时性存储,在业务系统中缓存可以避免数据库性能不够引发的宕机。
消息中间件也就是消息队列MQ,Redis一般不用。


数据结构

Redis的所有数据都是以KV键值对的形式存在的。

K作为唯一标识符,唯一标识一条数据,固定为String类型。
V真正存储数据,有多种类型(String、Hash、List、Set、Zset、BitMap、HypeLogLog)。

Redis类似Java中的Map集合:

Map<String,T> &#61; Redis存储

写就是指定KV&#xff0c;读只需要给定K。


数据类型

举个栗子&#xff1a;


KeyValue类型Value值应用场景
pv_20200101String10000一般用于存储单个数据指标的结果
person001Hashname:laoer,age:20 sex female用于存储整个对象所有属性值
uvList100,200,300,100,600有序允许重复的集合&#xff0c;每天获取最后一个值
uv_20200101Setuserid1,userid2,userid3,userid4……无序且不重复的集合&#xff0c;直接通过长度得到UV
top10_productZset10000-牙膏,9999-玩具,9998-电视……有序不可重复的集合&#xff0c;统计TopN
user_filterBitMap0101010101010000000011010将一个字符串构建位&#xff0c;通过0和1来标记每一位
product_20200101HyperLogLogproductid1&#xff0c;id2……类似于Set集合&#xff0c;底层实现原理不一样&#xff0c;数据量大的情况下&#xff0c;性能会更好

String类型

KV&#xff1a;【String&#xff0c;String】&#xff0c;类似于Java中Map集合的一条KV。


Hash类型

KV&#xff1a;【String&#xff0c;Map集合】&#xff1a;Map集合的嵌套&#xff0c;Map集合中的元素是无序的&#xff1a;

K V
person1 name&#61;zhangsan,age&#61;18,sex&#61;1,addr&#61;shanghai
person2 name&#61;lisi,age&#61;18,sex&#61;1,addr&#61;shanghai

List类型

KV&#xff1a;【String&#xff0c;List】&#xff1a;有序且可重复。


Set类型

KV&#xff1a;【String&#xff0c;Set】&#xff1a;无序且不重复。


Zset类型

KV&#xff1a;【String&#xff0c;TreeMap集合】&#xff1a;Value也类似于Map集合&#xff0c;但是TreeMap是有序的Map集合&#xff0c;故Zset是有序且不可重复的。


命令

通用命令

keys&#xff1a;列举当前数据库的所有key&#xff1a;

keys * 列举所有key
keys a* 列举所有a开头的key

del K&#xff1a;删除某个key&#xff1a;

del s1 删除key&#61;s1的KV键值对

exists K&#xff1a;判断某个key是否存在&#xff1a;

exists s1 判断是否有s1这个键存在

type K&#xff1a;判断某个key对应的value的类型&#xff08;key都是String类型的&#xff0c;这条命令当然也就不是判断key自己的类型&#xff09;&#xff1a;

type s1 判断key&#61;s1的键值对的value的类型

expire K t&#xff08;过期时间&#xff09;&#xff1a;设置某个key的过期时间&#xff08;计时结束后该kv对会被自动删除&#xff09;&#xff1a;

expire s1 10 10秒后删除s1的键值对

ttl K&#xff1a;查看某个key剩余的存活时间&#xff08;倒计时场景经常用&#xff09;&#xff1a;

ttl s1 查看s1的kv对的剩余存活时间&#xff0c;删除后再次执行是负数

select N:切换数据库&#xff1a;

select 1 切换数据库为db1

move K N&#xff1a;将某个kv对移动到某个数据库中&#xff1a;

move s1 1 将&#xff08;默认db0&#xff0c;切换后为当前db&#xff09;数据库中的s1的键值对数据移动到db1中

flushdb&#xff1a;清空当前数据库的所有key。
flushall&#xff1a;清空所有数据库的所有key。


String类型的常用命令

set&#xff1a;给String类型的Value的进行赋值或者更新&#xff1a;set K V&#xff1b;
get&#xff1a;读取String类型的Value的值&#xff1a;get K&#xff1b;
mset&#xff1a;用于批量写多个String类型的KV&#xff1a;mset K1 V1 K2 V2 ……&#xff1b;
mget&#xff1a;用于批量读取String类型的Value&#xff1a;mget K1 K2 K3 ……&#xff1b;
setnx&#xff1a;只能用于新增数据&#xff0c;当K不存在时可以进行新增&#xff08;搭配expire来使用&#xff0c;可以构建抢占锁&#xff09;&#xff1a;setnx K V&#xff1b;
incr&#xff1a;用于对数值类型的字符串进行递增&#xff0c;递增1&#xff1a;incr K&#xff1b;
incrby&#xff1a;指定对数值类型的字符串增长固定的步长&#xff1a;incrby K N&#xff1b;
decr&#xff1a;对数值类型的数据进行递减&#xff0c;递减1&#xff1a;decr K&#xff1b;
decrby&#xff1a;按照指定步长进行递减&#xff1a;decrby K N&#xff1b;
incrbyfloat&#xff1a;基于浮点数递增&#xff08;C语言浮点数会丢失精度&#xff09;&#xff1a;incrbyfloat K N&#xff1b;
strlen&#xff1a;统计字符串的长度&#xff1a;strlen K&#xff1b;
getrange&#xff1a;用于截取字符串&#xff1a;getrange s2 startnum endnum&#xff1b;


Hash类型的常用命令

hset&#xff1a;用于为某个K添加一个属性&#xff1a;hset K k v&#xff1b;
hget&#xff1a;用于获取某个K的某个属性的值&#xff1a;hget K k&#xff1b;
hmset&#xff1a;批量的为某个K赋予新的属性&#xff1a;hmset K k1 v1 k2 v2 ……&#xff1b;
hmget&#xff1a;批量的获取某个K的多个属性的值&#xff1a;hmget K k1 k2 k3……&#xff1b;
hgetall&#xff1a;获取所有属性的值&#xff1a;hgetall K&#xff1b;
hdel&#xff1a;删除某个属性&#xff1a;hdel K k1 k2 ……&#xff1b;
hlen&#xff1a;统计K对应的Value总的属性的个数&#xff1a;hlen K&#xff1b;
hexists&#xff1a;判断这个K的V中是否包含这个属性&#xff1a;hexists K k&#xff1b;
hvals&#xff1a;获取所有属性的value&#xff1a;hvals K&#xff1b;


List类型的常用命令

lpush&#xff1a;将每个元素放到集合的左边&#xff0c;左序放入&#xff1a;lpush K e1 e2 e3……&#xff1b;
rpush&#xff1a;将每个元素放到集合的右边&#xff0c;右序放入&#xff1a;rpush K e1 e2 e3……&#xff1b;
lrange&#xff1a;通过下标的范围来获取元素的数据&#xff08;从左往右的下标从0开始【0 5】&#xff0c;从右往左的下标从-1开始【-5 -1】&#xff0c;∴一定是从小的到大的下标&#xff1a;lrange K 0 -1&#xff1a;所有元素&#xff09;&#xff1a;lrange K startnum endnum&#xff1b;
llen&#xff1a;统计集合的长度&#xff1a;llen K&#xff1b;
lpop&#xff1a;删除左边的一个元素&#xff1a;lpop K&#xff1b;
rpop&#xff1a;删除右边的一个元素&#xff1a;rpop K&#xff1b;


Set类型的常用命令

sadd&#xff1a;添加元素到Set集合中&#xff1a;sadd K e1 e2 e3 e4 e5……&#xff1b;
smembers&#xff1a;查看Set集合的所有成员&#xff1a;smembers K&#xff1b;
sismember&#xff1a;判断是否包含这个成员&#xff1a;sismember K e1&#xff1b;
srem&#xff1a;删除其中某个元素&#xff1a;srem K e&#xff1b;
scard&#xff1a;统计集合长度&#xff1a;scard K&#xff1b;
sunion&#xff1a;取两个集合的并集&#xff1a;sunion K1 K2&#xff1b;
sinter&#xff1a;取两个集合的交集&#xff1a;sinter K1 K2&#xff1b;


Zset类型的常用命令

zadd&#xff1a;用于添加元素到Zset集合中&#xff1a;zadd K score1 k1 score2 k2 ……&#xff1b;
zrange&#xff1a;范围查询&#xff08;默认按照key的降序排列&#xff0c;使用withscores会显示key的内容&#xff09;&#xff1a;zrange K start end [withscores]&#xff1b;
zrevrange&#xff1a;倒序查询&#xff1a;zrevrange K start end [withscores]&#xff1b;
zrem&#xff1a;移除一个元素&#xff1a;zrem K k1&#xff1b;
zcard&#xff1a;统计集合长度&#xff1a;zcard K&#xff1b;
zscore&#xff1a;获取评分&#xff08;获取value对应的key&#xff09;&#xff1a;zscore K k&#xff1b;


BitMap类型的常用命令

通过一个String对象的存储空间来构建位图&#xff0c;每位&#xff08;bit&#xff09;当然只能表示0/1。学过嵌入式的都很容易理解&#xff1a;
Redis的一个String最大为512MB&#xff08;512MB也就是2^(9&#43;10&#43;10)Byte&#xff0c;再*8换算后为2^(9&#43;10&#43;10&#43;3)bit&#xff0c;换句话说&#xff0c;Redis的String是32位的&#xff0c;不是64位或者8位16位。32位&#xff08;西门子PLC称之VW&#xff0c;双字&#xff09;&#61;4字节&#xff08;西门子PLC称之VB&#xff0c;字节&#xff09;。

和数组的下标一样&#xff0c;BitMap也是从0开始的&#xff08;不需要关心大小端的问题&#xff09;&#xff0c;使用时&#xff0c;每一位默认都&#61;0&#xff0c;也可以直接操作使得置0和置1。C语言可以直接操作寄存器的好处就体现出来了&#xff01;&#xff01;&#xff01;如果使用位图的某一位来对应用户id&#xff0c;读取数据时&#xff0c;发现用户id就将该id对应的的那一位置位&#xff0c;结束后计数位图中1的个数就是UV&#xff01;&#xff01;&#xff01;也不需要SQL中DISTINCT去重&#xff01;&#xff01;&#xff01;

setbit&#xff1a;修改某一位的值&#xff1a;set K 脚标 1&#xff1b;
getbit&#xff1a;查看某一位的值&#xff1a;getbit K 角标&#xff1b;
bitcount&#xff1a;统计位图中1的个数&#xff08;2个脚标是字节数&#xff09;&#xff1a;bitcount K startnum endnum&#xff1b;
bitop&#xff1a;位图的按位运算&#xff08;and与、or或、not取反、xor异或&#xff09;&#xff1a;bitop and bit3 bit1 bit2是把bit1和bit2相与的结果放到bit3&#xff1b;


HyperLogLog类型的常用命令

对&#xff01;&#xff01;&#xff01;没看错&#xff0c;就是2个Log。

HyperLogLog类似Set集合&#xff0c;用于实现数据的去重&#xff0c;但是底层实现原理不同&#xff0c;适合于大数据量的情况下使用&#xff08;存在误差率&#xff09;。

pfadd&#xff1a;添加元素&#xff1a;pfadd K e1 e2 e3......&#xff1b;
pfcount&#xff1a;统计个数&#xff1a;pfcount K&#xff1b;
pfmerge&#xff1a;实现集合合并&#xff1a;pfmerge pfrs K1 K2......&#xff1b;


Windows版Redis

部署

随便找个Redis低版本的试试&#xff0c;测试用&#xff0c;哪个版本都差不多。

搞到手的是个Zip包&#xff0c;和常规的软件一样&#xff0c;解压缩就能用。。。笔者选择解压到C盘&#xff0c;路径纯英文即可。里边有这些玩意儿&#xff1a;


目录/文件备注
redis-benchmark.exeredis的性能测试工具
redis-check-aof.exeaof文件的检查和修复工具
redis-check-dump.exerdb文件的检查和修复工具
redis-cli.execlient 客户端访问命令
redis-server.exe服务器启动程序
redis.window.conf配置文件&#xff0c;这是个文本文件

测试

当然是先启动server才能启动client。。。先双击redis-server.exe&#xff0c;首次使用Win10会阻挠&#xff0c;需要同意使用网络&#xff1a;

发现Redis使用的是6379端口。如果服务端闪退&#xff0c;就搞个bat脚本强制按照配置文件的内容来启动&#xff1a;

redis-server.exe redis.windows.conf


这个脚本需要放到解压的文件夹里才能正常使用&#xff0c;都懂的。。。

双击redis-cli.exe可以启动客户端&#xff1a;

很“智能”&#xff0c;刚输入set就提醒可以修改后边的参数。。。比shell体验好多了。。。

127.0.0.1:6379> set s1 hadoop
OK
127.0.0.1:6379> keys *
1) "s1"
127.0.0.1:6379> set s2 hive
OK
127.0.0.1:6379> keys *
1) "s1"
2) "s2"
127.0.0.1:6379> get s1
"hadoop"
127.0.0.1:6379> get s2
"hive"
127.0.0.1:6379>

keys * 就是SQL中的SELECT*


桌面工具

这年头连SQLite都有很多客户端&#xff0c;Redis当然也有很多种客户端&#xff08;Redis Desktop Manager、RedisStudio、RedisClient等&#xff09;&#xff0c;笔者随便玩玩&#xff1a;

正常的下一步安装。。。



选用连接本机&#xff08;localhost就是127.0.0.1&#xff09;&#xff0c;之后就出现了和SQLite Studio的差不多的树形结构&#xff1a;

可以看出Redis默认有db0~db15攻击16个数据库&#xff0c;且默认使用的是db0数据库&#xff0c;也能看到之前配置的数据。

一般是Linux用Redis&#xff0c;Windows貌似用的不多。。。


Linux版Redis

部署

先安装到一台机再说。上传安装包&#xff1a;

cd /export/software/
rz

解包&#xff1a;

tar -zxvf redis-3.2.8.tar.gz -C /export/server/

由于Redis是地球最强的C语言写的&#xff0c;不是Java的那种跨平台通用的Jar包&#xff0c;需要编译才能用&#xff0c;使用yum安装gcc依赖以便使用gcc编译&#xff1a;

yum -y install gcc-c&#43;&#43; tcl

安装好gcc就可以编译&#xff1a;

cd /export/server/redis-3.2.8/
make

安装&#xff1a;

make PREFIX&#61;/export/server/redis-3.2.8-bin install

修改配置&#xff1a;

cp /export/server/redis-3.2.8/redis.conf /export/server/redis-3.2.8-bin/
mkdir -p /export/server/redis-3.2.8-bin/logs
mkdir -p /export/server/redis-3.2.8-bin/datas
cd /export/server/redis-3.2.8-bin/
vim redis.conf

然后小心地修改4处&#xff0c;使Redis可以使用网卡&#xff08;61行&#xff09;、后台运行&#xff08;128行&#xff09;、存储服务器日志&#xff08;163行&#xff09;、持久化数据存储&#xff08;247行&#xff09;&#xff1a;

bind node1

daemonize yes

logfile "/export/server/redis-3.2.8-bin/logs/redis.log"

dir /export/server/redis-3.2.8-bin/datas/

记得保存。

创建软连接&#xff08;类似Win的快捷方式&#xff09;以便调用及修改&#xff1a;

cd /export/server
ln -s redis-3.2.8-bin redis

配置环境变量&#xff1a;

vim /etc/profile

找个空行插入&#xff1a;

# REDIS HOME
export REDIS_HOME&#61;/export/server/redis
export PATH&#61;:$PATH:$REDIS_HOME/bin

先保存&#xff0c;再重新加载环境变量&#xff1a;

source /etc/profile

OK&#xff0c;配置完成&#xff0c;试试能不能用。


启动


服务端

国际惯例&#xff0c;先启动服务端&#xff1a;

/export/server/redis/bin/redis-server /export/server/redis/redis.conf

当然也可以自己写个shell脚本&#xff0c;就不必这么麻烦&#xff1a;

vim /export/server/redis/bin/redis-start.sh

写上内容&#xff1a;

#!/bin/bash
REDIS_HOME&#61;/export/server/redis
$REDIS_HOME/bin/redis-server $REDIS_HOME/redis.conf

增加可执行权限&#xff1a;

chmod u&#43;x /export/server/redis/bin/redis-start.sh

由于配置了环境变量&#xff0c;任意目录都可以调用脚本&#xff1a;

[root&#64;node1 server]# cd
[root&#64;node1 ~]# redis-
redis-benchmark redis-check-aof redis-check-rdb redis-cli redis-sentinel redis-server redis-start.sh
[root&#64;node1 ~]# redis-start.sh

启动后&#xff1a;

[root&#64;node1 ~]# ps -ef |grep redis
root 5110 1 0 17:48 ? 00:00:00 /export/server/redis/bin/redis-server node1:6379
root 5118 1772 0 17:48 pts/0 00:00:00 grep --color&#61;auto redis

可以看到相关的进程&#xff08;6379端口的进程就是Redis的服务端&#xff09;。


客户端

/export/server/redis/bin/redis-cli -h node1 -p 6379

启动后&#xff1a;

[root&#64;node1 ~]# /export/server/redis/bin/redis-cli -h node1 -p 6379
node1:6379>

同意很“智能”&#xff1a;

简单试试&#xff1a;

node1:6379> keys *
(empty list or set)
node1:6379> set s1 hadoop
OK
node1:6379> keys *
1) "s1"
node1:6379> get s1
"hadoop"

和Win10上测试的效果一致&#xff0c;安装成功。


关闭


客户端

对话框输入exit就可以退出。


服务端

客户端可以使用命令shutdown让服务端关闭&#xff08;注意&#xff01;&#xff01;&#xff01;是Redis客户端中输入命令&#xff0c;不是shell中shutdown关机&#xff09;。如果一定要要shell中关闭&#xff0c;可以&#xff1a;

/export/server/redis/bin/redis-cli -h node1 -p 6379 shutdown

这种方式其实也是通过客户端实现的关闭。

如果先关闭了客户端&#xff0c;也有办法关闭服务端。。。惯用的当然是先找到Redis对应的服务端的pid再kill -9&#xff08;手动2步&#xff09;。或者高端的做法&#xff08;Linux中一切皆文件&#xff0c;运行中的进程也在文件中有记录&#xff0c;直接从文件中抓获进程号即可&#xff09;&#xff1a;

kill -9 &#96;cat /var/run/redis_6379.pid&#96;

如果不是root用户&#xff0c;可能有权限级别不够的问题&#xff0c;sudo开头即可&#xff08;玩树莓派和Ubuntu那会儿好像每一句都是sudo开头。。。&#xff09;&#xff1a;

sudo cat /var/run/redis_6379.pid

可以看到进程号。

当然大部分情况下不可能手动写命令&#xff0c;用类似JDBC的方式使用编程语言自动调用命令显然更高效。下一篇讲述Jedis。














超强干货来袭


云风专访:近40年码龄,通宵达旦的技术人生


推荐阅读
author-avatar
永远在等一个人--嘉儿
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有